using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using ComponentFactory.Krypton.Toolkit;
using KryptonPalettesComposer.Common;
using System.Reflection;
using System.IO;
using Microsoft.Win32;
using System.Linq;
using System.Xml;

namespace KryptonPalettesComposer.Forms
{
    public partial class MainForm : ComponentFactory.Krypton.Toolkit.KryptonForm
    {
        #region constructor
        public MainForm()
        {
            syncupBackColor();
            KryptonManager.GlobalPaletteChanged += new EventHandler((s, e) => syncupBackColor());
            this.AllowFormChrome = !Utils.IsCompositionEnabled;
            this.AllowStatusStripMerge = false;

            InitializeComponent();

            Text += " " + Assembly.GetExecutingAssembly().GetName().Version;
        }
        #endregion

        #region form events
        private void MainForm_Load(object sender, EventArgs e)
        {
            // search for the toolkit assemlby
            getToolkitAssembly();

            // search for palettes
            searchPalettes();
        }

        private void btnAdd_Click(object sender, EventArgs e)
        {
            if (openPaletteDialog.ShowDialog() == DialogResult.OK)
            {
                // add files to listview
                addFiles(openPaletteDialog.FileNames);
            }
        }

        private void btnRemove_Click(object sender, EventArgs e)
        {
            if (lstViewPalettes.SelectedItems.Count == 1)
            {
                // remove selected item from list
                lstViewPalettes.SelectedItems[0].Remove();
            }
        }

        private void lstViewPalettes_SelectedIndexChanged(object sender, EventArgs e)
        {
            btnRemove.Enabled = lstViewPalettes.SelectedItems.Count == 1;
        }


        private void lstViewPalettes_Click(object sender, EventArgs e)
        {
            if (lstViewPalettes.SelectedItems.Count == 1)
            {
                lstViewPalettes.SelectedItems[0].BeginEdit();
            }
        }

        private void btnToolkitAssembly_Click(object sender, EventArgs e)
        {
            openAssemblyDialog.FileName = txtToolkitAssembly.Text;
            if (openAssemblyDialog.ShowDialog() == DialogResult.OK)
                txtToolkitAssembly.Text = openAssemblyDialog.FileName;
        }

        private void btnAssemblyPath_Click(object sender, EventArgs e)
        {
            outputAssemblyDialog.FileName = txtOutputAssembly.Text;
            if (outputAssemblyDialog.ShowDialog() == DialogResult.OK)
            {
                txtOutputAssembly.Text = outputAssemblyDialog.FileName;
                txtNameSpace.Text = Path.GetFileNameWithoutExtension(outputAssemblyDialog.FileName);
            }
        }

        private void btnCompose_Click(object sender, EventArgs e)
        {
            if (checkInput())
            {
                btnCompose.Enabled = false;
                try
                {
                    prgBar.Maximum = lstViewPalettes.Items.Count + 1;
                    prgBar.Value = 0;
                    prgBar.Visible = true;
                    lblStatus.Text = "";
                    lblStatus.Visible = true;

                    Composer composer = new Composer(txtOutputAssembly.Text, txtNameSpace.Text, txtToolkitAssembly.Text);

                    foreach (ListViewItem item in lstViewPalettes.Items)
                    {
                        lblStatus.Text = string.Format("Adding palette {0}...", item.Text);
                        Application.DoEvents();
                        composer.AddPalette(item.SubItems[1].Text, item.Text);
                        prgBar.Value++;
                    }
                    lblStatus.Text = "Compiling...";
                    Application.DoEvents();
                    string result = composer.Finish();
                    prgBar.Value++;

                    lblStatus.Text = "Finished!";
                    Application.DoEvents();

                    if (!string.IsNullOrEmpty(result))
                        MessageBox.Show(result, "Compiler errors", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    btnCompose.Enabled = true;
                }
            }
        }

        #endregion

        #region private methods
        /// <summary>
        /// Search in current directory for palettes
        /// </summary>
        private void searchPalettes()
        {
            // get current dir
            string directory = Directory.GetParent(Assembly.GetExecutingAssembly().Location).FullName;

            // search for xml-files
            string[] files = Directory.GetFiles(directory, "*.xml");

            // add found files
            addFiles(files);

            // search in subfolder "Palettes"
            directory = Path.Combine(directory, "Palettes");

            if (Directory.Exists(directory))
            {
                // search for xml-files
                files = Directory.GetFiles(directory, "*.xml");

                // add found files
                addFiles(files);
            }
        }

        /// <summary>
        /// Searches the toolkit assemlby
        /// </summary>
        private void getToolkitAssembly()
        {
            RegistryKey registryKey = Registry.ClassesRoot.OpenSubKey(@"Installer\Assemblies", false);

            IEnumerable<string> keys = registryKey.GetSubKeyNames().Where(n => n.Contains("ComponentFactory.Krypton.Toolkit"));

            if (keys.Count() > 0)
            {
                txtToolkitAssembly.Text = keys.ElementAt(0).Replace("|", "\\");
            }
        }

        /// <summary>
        /// Add given files to Listview
        /// </summary>
        /// <param name="filenames"></param>
        private void addFiles(string[] filenames)
        {
            foreach (string filename in filenames)
            {
                ListViewItem item = lstViewPalettes.Items.Add(Path.GetFileNameWithoutExtension(filename));
                item.SubItems.Add(filename);
                item.SubItems.Add(getVersion(filename));
            }
        }

        /// <summary>
        /// Get the version the pallete is for
        /// </summary>
        /// <param name="filename"></param>
        /// <returns></returns>
        private string getVersion(string filename)
        {
            string result = "";

            try
            {
                XmlDocument doc = new XmlDocument();
                doc.Load(filename);

                XmlAttribute attrib = doc.DocumentElement.Attributes["Version"];
                if (attrib != null)
                    result = attrib.Value;
            }
            catch
            {
                result = "-";
            }

            return result;
        }

        /// <summary>
        /// checks the controls for valid input
        /// </summary>
        /// <returns></returns>
        private bool checkInput()
        {
            bool result = true;
            string msg = "";

            if (String.IsNullOrEmpty(txtOutputAssembly.Text))
            {
                result = false;
                msg = "Please choose an output assembly!";
            }
            else
                if (File.Exists(txtOutputAssembly.Text))
                {
                    if (MessageBox.Show("Output assembly already exists. Overwrite it?", "File exists", MessageBoxButtons.YesNo, MessageBoxIcon.Question) == DialogResult.No)
                        result = false;
                }
                else
                    if (String.IsNullOrEmpty(txtNameSpace.Text))
                    {
                        result = false;
                        msg = "Please provide a namespace!";
                    }
                    else
                        if (String.IsNullOrEmpty(txtToolkitAssembly.Text))
                        {
                            result = false;
                            msg = "Please provide a path to the ComponentFactory.Krypton.Toolkit assembly!";
                        }
                        else
                            if (!File.Exists(txtToolkitAssembly.Text))
                            {
                                result = false;
                                msg = "The ComponentFactory.Krypton.Toolkit assembly does not exists at the specified path!";
                            }
                            else
                                if (lstViewPalettes.Items.Count == 0)
                                {
                                    result = false;
                                    msg = "Please choose a palette to compose!";
                                }
                                else
                                {
                                    string lastName = "";
                                    foreach (ListViewItem item in lstViewPalettes.Items)
                                    {
                                        if (String.IsNullOrEmpty(item.Text))
                                        {
                                            result = false;
                                            msg = "Please provide a name for this palette!";
                                            break;
                                        }
                                        else if (item.Text == lastName)
                                        {
                                            result = false;
                                            msg = string.Format("The palette name {0} already exists!", lastName);
                                            break;
                                        }
                                        else if (string.IsNullOrEmpty(item.SubItems[0].Text))
                                        {
                                            result = false;
                                            msg = "Please provide a file for this palette!";
                                            break;
                                        }

                                        lastName = item.SubItems[0].Text;
                                    }
                                }

            if (!result && !String.IsNullOrEmpty(msg))
                MessageBox.Show(msg, "Validation", MessageBoxButtons.OK, MessageBoxIcon.Error);

            return result;
        }

        private void syncupBackColor()
        {
            this.BackColor = KryptonManager.CurrentGlobalPalette.GetBackColor1(PaletteBackStyle.PanelClient, PaletteState.Normal);
        }
        #endregion

    }
}